#ifndef __WS_SERVER_H__
#define __WS_SERVER_H__

#include "thread_pool.h"
#include "cam_tele.h"
#include "base.pb.h"
#include "state_manager.h"
#include "cam_wide.h"
#include "system.h"
#include "rgb_power.h"
#include "motor_controller.h"
#include "track.h"
#include "focus.h"
#include "astro.h"
#include "dwarf2_panorama.h"
#include "iTips.h"

#include "libhv/WebSocketServer.h"
#include "libhv/EventLoop.h"

using namespace hv;

class WsServer {
public:
    WsServer();
    ~WsServer();

    int startWsServer();
    static int dispatchMessage(WsServer* ws_server, const std::string& msg, int channel_id);
    int handleCameraMessage(WsPacket& ws_packet);
    int handleAstroMessage(WsPacket& ws_packet);
    int handleCamWideMessage(WsPacket& ws_packet);
    int handleSystemMessage(WsPacket& ws_packet);
    int handleRgbPowerMessage(WsPacket& ws_packet);
    int handleMotorMessage(WsPacket& ws_packet);
    int handleTrackMessage(WsPacket& ws_packet);
    int handleFocusMessage(WsPacket& ws_packet);
    int handlePanormaMessage(WsPacket& ws_packet);
    int handleNotifyMessage(WsPacket& ws_packet);
    int handleITipsMessage(WsPacket& ws_packet);

private:
    void addChannel(const WebSocketChannelPtr& channel);
    void removeChannel(const WebSocketChannelPtr& channel);
    // int foreachChannel(std::function<void(const WebSocketChannelPtr& channel)> fn);
    void addClientId(int channel_id, const std::string& client_id, int major_version, int minor_version);
    void removeClientId(const std::string& client_id);
    void UpdateMasterClientId();
    void checkAndSwitchMaster();

public:
    ThreadPool* p_thread_pool_;
    CamTele cam_tele_;
    StateManager* p_state_manager;
    CamWide cam_wide_;
    System system_;
    RgbPower rgb_power_;
    MotorController motor_controller_;
    Track track_;
    Focus focus_;
    Astro& astro_ = Astro::astro();
    Dwarf2Panorama panorama_;
    ITips& itips_ = ITips::itips();

    WebSocketService ws;

private:
    websocket_server_t server;
};

#endif